package org.gaaidou.ptarmigan.springboot.core.web;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.*;
import org.springframework.lang.Nullable;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;


@ControllerAdvice
@Slf4j
public class ExceptionHandlerAdvice extends ResponseEntityExceptionHandler {

    @ExceptionHandler({
            IllegalStateException.class,
            IllegalArgumentException.class
    })
    public ResponseEntity<ProblemDetail> handleIllegalException(Exception ex) {
        ProblemDetail problemDetail = new ProblemDetail(HttpStatus.BAD_REQUEST.value());
        problemDetail.setDetail(ex.getMessage());
        return ResponseEntity.badRequest().body(problemDetail);
    }

    @ExceptionHandler(Throwable.class)
    public ResponseEntity<ProblemDetail> handleThrowable(Throwable ex) {
        log.error("Exception catch exception: {}", ex.getMessage(), ex);
        return ResponseEntity.internalServerError().body(new ProblemDetail(HttpStatus.SERVICE_UNAVAILABLE.value()));
    }

    @Override
    public ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex,
                                                               HttpHeaders headers,
                                                               HttpStatusCode status,
                                                               WebRequest request) {
        ResponseEntity<Object> responseEntity = super.handleMethodArgumentNotValid(ex, headers, status, request);
        if (responseEntity.getBody() instanceof org.springframework.http.ProblemDetail springProblemDetail) {

            ProblemDetail problemDetail = new ProblemDetail(springProblemDetail);
            problemDetail.setInvalidParams(ex.getFieldErrors()
                    .stream()
                    .map(v -> new InvalidParam(v.getField(), v.getDefaultMessage()))
                    .toList());
            return createResponseEntity(problemDetail, headers, status, request);

        }
        return responseEntity;
    }

    @Override
    public ResponseEntity<Object> createResponseEntity(@Nullable Object body, HttpHeaders headers, HttpStatusCode statusCode, WebRequest request) {
        return ResponseEntity.status(statusCode).headers(headers).contentType(MediaType.APPLICATION_PROBLEM_JSON).body(body);
    }
}
